package com.netty.pro.netty.websocket;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.stream.ChunkedWriteHandler;

/**
 * @author xuzn
 * @ClassName: WebsocketServer
 * @ProjectName netty-pro
 * @date 2020/3/16/20:15
 */
public class WebsocketServer {

  public static void main(String[] args) throws Exception {
    EventLoopGroup bossGroup = new NioEventLoopGroup(1);
    EventLoopGroup workerGroup = new NioEventLoopGroup(8);
    try {
      ServerBootstrap bootstrap = new ServerBootstrap();
      bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
              .handler(new LoggingHandler())
              .childHandler(new ChannelInitializer<SocketChannel>() {
                @Override
                protected void initChannel(SocketChannel ch) throws Exception {
                  ChannelPipeline pipeline = ch.pipeline();
                  // 基于http协议,使用http编解码
                  pipeline.addLast("httpCodec", new HttpServerCodec());
                  // 以块的方式写入,添加ChunkedWriteHandler处理器
                  pipeline.addLast(new ChunkedWriteHandler());

                  /**
                   * http数据在传输过程中是分段的,HttpObjectAggregator可以将多个段进行聚合
                   * 因为数据分段,所以浏览器发送大量数据时就会发出多次http请求
                   */
                  pipeline.addLast(new HttpObjectAggregator(8192));

                  /**
                   * 对应websocket,它的数据是以帧的形式传递
                   * WebSocketFrame
                   * 浏览器请求时: ws://localhost:7000/abc-->表示请求的uri
                   * WebSocketServerProtocolHandler核心功能将http协议升级为ws协议,保持长链接
                   */
                  pipeline.addLast(new WebSocketServerProtocolHandler("/abc"));

                  pipeline.addLast(new TextWebsocketFrameHandler());
                }
              });
      ChannelFuture channelFuture = bootstrap.bind(7000).sync();
      channelFuture.channel().closeFuture().sync();
    } finally {
      bossGroup.shutdownGracefully();
      workerGroup.shutdownGracefully();
    }
  }
}
